iT邦幫忙

2021 iThome 鐵人賽

DAY 8
2
Modern Web

[ 重構倒數30天,你的網站不Vue白不Vue ] 系列 第 8

[重構倒數第23天] - Tab 的 page 加入 router

  • 分享至 

  • xImage
  •  

前言

該系列是為了讓看過Vue官方文件或學過Vue但是卻不知道怎麼下手去重構現在有的網站而去規畫的系列文章,在這邊整理了許多我自己使用Vue重構很多網站的經驗分享給讀者們。

我們在開發專案的時候不是所有的專案都是採用前後端分離的方式來進行開發,有許多專案是建立在後端框架內,然後去撰寫前端 view 的部分,像是 Laravel 或是 Django 等等,這類的web後端框架不只是 render,連 router 也是在後端定義的,所以基本上前端這邊開發上面就是寫單純的 html、css 還有 javascript,但是當你開始接手這類型的專案的時候,多少都會希望採用現在比較流行的開發方式去開發前端,所以我們會在後端的框架內載入Vue改寫以前單純用 html、css 還有 javascript 寫的頁面,不過當我們今天在使用 Vue 開發的時候,我們就可以在一些只有前端處理的頁面,透過 vue-router 來自定義前端的 router ,這樣我們就不需要再透過後端定義的方式來處理網址的部分。

vue-router 基本使用方式

我們可以使用 vue-router 來幫我們達成透過 client side render 的效果,也可以透過前端的方式來自定義 router ,這也是我們所謂的 SPA ( single-page application ),我們來快速的看一下如何使用 vue-router。

首先我們應該先來載入vue-router,我們先假設我們接手的專案是很傳統的MVC架構,不是透過 Vue-cli 或是其他自動化工具整合過的專案,所以無法透過 npm 的方式來進行安裝,所以我們可以透過CDN的方式來引入。

注意!!! 這邊我們要載入的 vue-router 版本要是 v4.x 的版本, v4.x 以上的版本才可以給 Vue3 去做使用。

我們來看一下 vue-router 載入後的設定

import { createRouter, createWebHistory } from "vue-router"

const router = createRouter({
  history: createWebHistory(),
});

createApp(App).use(router).mount("#app");

首先我們從 Global 中的 VueRouter 取出 createRoutercreateWebHashHistory 這兩個函式,在這邊我列出三個非常重要的 API 特別來介紹

  • createRouter:創建一個可以被 Vue 使用的 Router 實體。

  • createWebHistory:可以創建一個 HTML5 的 Web History 切換頁面 ( 需要有http的協議提供服務 ) 。

  • createWebHashHistory:可以創建 hash History 來切換頁面 ( 可以使用在沒有 server 的 web上面,或是當 server 不能處理任意router 的時候,可以使用,只是網址後面會帶入 # )。

    例 : https://www.demo.com/#/about

再來我們要新增 router 的內容

// component A
const Home = { template: "<div>Home</div>" };

// component B
const About = { template: "<div>About</div>" };

// 定義 router 的內容
const routes = [
  { path: "/", component: Home },
  { path: "/about", component: About }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

我在上面定義了兩個 component,這兩個 component 就是我要切換的頁面,然後塞入 createRouter實體內,這樣一來我們 Vue 就具備了這兩個 component 以及router的資訊,接下來我們要把頁面的內容給 render 到頁面上面。

<div id="app">
  <nav>
    <router-link to="/">Go to Home</router-link>
    <router-link to="/about">Go to About</router-link>
  </nav>
  <router-view></router-view>
</div>
  • router-view:當掛載 vue-router 後,可以直接使用 <router-view>這個組件來 render頁面的內容。

  • router-link:可以透過<router-link to="/about">的指定方式,來切換頁面,預設 router-link 會編譯成 <a>,我們也可以透過它的 API 來改編譯後的html tag。

這樣子我們就可以在傳統的專案上面使用框架的方式來開發還有定義 router,只不過這要特別注意,vue-router是屬於 client side render 的方式,也就是說它的頁面都是透過 javascript 的方式給 render 出來,自然SEO的效果就差了點,所以如果你是要著重在SEO的網站上面,盡量不要把重點的SEO頁面用 vue-router 的方式實作。

然後我們需要做一點的防呆處理

const routes = [
  { path: "/", component: Home },
  { path: "/about", component: About },
  { path: "/*", redirect: "/"}
];

我們在 routes 的最後新增一個 /* 以防止一般 user 隨便輸入,所以當今天 user 隨便輸入網址的時候,如果跟 routes 裡面沒有一個 path 符合的話,就會比對到最後的 /* 這個度部分,去執行 redirect 轉址到 /這個路徑下。

注意! { path: "/*", redirect: "/"} 一定要放在最後,如果放在前面的話,它後面的 routes 就不會被比對,而是會直接 redirect,這點一定要特別的注意,關於 vue-router 的更多使用方式可以再參考官網 https://next.router.vuejs.org/guide/#javascript

實際用用看

我們來看一下一般分頁裡面有出現tab的區塊的時候,應該怎麼做

Vue Router

嵌套路由 (Nested Routes)

首先我們會需要定義一下 /about 底下的 router,這邊我們使用嵌套路由 (Nested Routes) ,我們先到 main.js

import { createApp } from "vue";
import { createRouter, createWebHistory } from "vue-router";
import App from "./App.vue";
import Home from "./view/Home.vue";
import About from "./view/About.vue";
import Html from "./components/about/html.vue";
import Css from "./components/about/css.vue";
import Js from "./components/about/js.vue";

const routes = [
  { path: "/", component: Home },
  {
    path: "/about",
    component: About,
    children: [
      {
        path: "",
        component: Html
      },
      {
        path: "css",
        component: Css
      },
      {
        path: "js",
        component: Js
      }
    ]
  },
  { path: "/*", redirect: "/" }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

createApp(App).use(router).mount("#app");

Nested Routes 文件 :https://router.vuejs.org/guide/essentials/nested-routes.html#nested-routes

這邊的 children 就是讓我們去設定再 /about 之後的 router。

所以我們在 App.vue 的地方有放置 <router-view></router-view> ,去渲染不同的頁面,但是現在再 about 裡面也需要放 <router-view></router-view> ,去渲染 /about 後面的不同的頁面

about.vue

<template>
  <h1>about</h1>
  <div class="tab_box">
    <nav>
      <router-link to="/about/">html</router-link>
      <router-link to="/about/css">css</router-link>
      <router-link to="/about/js">js</router-link>
    </nav>
    <div class="content">
      <router-view></router-view>
    </div>
  </div>
</template>

這樣一來主根目錄下面的去讀取 App.vue 下面的 router-view,然後 /about 底下的就是 About.vue 下面的 router-view去 Render,非常的簡單就可以做出這種嵌套路由的網頁。

關於選取狀態的樣式!

我們在點擊 router-link 的時候,通常會要讓那個按鈕的狀態顯示被標記,所以我們會需要設定一個狀態的 class,但是其實 router-link 本身就有提供 active狀態的 class 去對應網址的部分,我們只需要填上css,就可以了達到 active狀態的呈現。

mike vue3 router

.router-link-exact-active 這個 class 就會是對應你的 router ,然後加入上去,所以我們就在這個樣式上面加一下

> a {
  &.router-link-exact-active {
    color: #fff;
    background-color: #498ba7;
  }
}

這樣就可以讀取到了,你會發現怎麼有兩個 active class。

  • router-link-active : 目前 router 符合 /about 就會出現,後面 /about/css 這樣也會出現。

  • router-link-exact-active : router 要完全符合定義好的 router 才會出現。

codesandbox 範例 : https://codesandbox.io/s/vue-nested-routes-zde77

先告一個段落

其實 vue-router 看官網就大概知道如何使用,但今天重點著重在 web重構上面的使用情境,我們應該要多多考慮使用者在實際的使用上面會有那些問題,而不是只把效果做出來就好。

QRcode

那如果對於Vue3不夠熟的話呢?

Ps. 購買的時候請登入或註冊該平台的會員,然後再使用下面連結進入網站點擊「立即購課」,這樣才可以讓我獲得更多的課程分潤,還可以幫助我完成更多豐富的內容給各位。

我有開設了一堂專門針對Vue3從零開始教學的課程,如果你覺得不錯的話,可以購買我課程來學習
https://hiskio.com/bundles/9WwPNYRpz?s=tc

那如果對於JS基礎不熟的朋友,我也有開設JS的入門課程,可以參考這個課程
https://hiskio.com/bundles/b9Rovqy7z?s=tc

訂閱Mike的頻道享受精彩的教學與分享

Mike 的 Youtube 頻道
Mike的medium
MIke 的官方 line 帳號,好友搜尋 @mike_cheng


上一篇
[重構倒數第24天] - You should use Skeleton
下一篇
[重構倒數第22天] - 減少 watch,改用 computed
系列文
[ 重構倒數30天,你的網站不Vue白不Vue ] 32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言